import { shaders } from "./shader.js";

async function init() {
    if (!navigator.gpu) {
        throw Error("WebGPU not supported.");
    }

    const adapter = await navigator.gpu.requestAdapter();
    if (!adapter) {
        throw Error("Couldn't request WebGPU adapter.");
    }

    const device = await adapter.requestDevice();
    device.lost.then(info=>{
        console.error(`WebGPU device was lost: ${info.message}`);

        // 'reason' will be 'destroyed' if we intentionally destroy the device.
        if(info.reason!=="destroyed"){
            // try again
            init();
        }
    });

    const shaderModule = device.createShaderModule({
        code: shaders,
    });

    const canvas = document.getElementById("gpuCanvas");
    const context = canvas.getContext("webgpu");

    // resizeObserver对象直接修改canvas尺寸
    const observer=new ResizeObserver(entries=>{
        for(const entry of entries){
            const canvas=entry.target;
            const width=entry.contentBoxSize[0].inlineSize;
            const height=entry.contentBoxSize[0].blockSize;
            // limit the size of the canvas to the largest size our device supports
            canvas.width=Math.max(1,Math.min(width,device.limits.maxTextureDimension2D));
            canvas.height=Math.max(1,Math.min(height,device.limits.maxTextureDimension2D));
            frame();
        }
    });
    // only observing the canvas
    observer.observe(canvas);

    context.configure({
        device: device,
        format: navigator.gpu.getPreferredCanvasFormat(),
        alphaMode: "premultiplied",
    });


    const vertices = new Float32Array([
        0.0, 0.6, 0, 1, 1, 0, 0, 1, -0.5, -0.6, 0, 1, 0, 1, 0, 1, 0.5, -0.6, 0, 1, 0,
        0, 1, 1,
    ]);

    // We need to get our data into a GPUBuffer. This type of buffer is stored in 
    // memory very tightly integrated with the GPU's cores to allow for the desired
    // high performance processing. As a side effect, this memory can't be accessed
    // by processes running on the host system, like the browser.

    const vertexBuffer = device.createBuffer({
        size: vertices.byteLength, // make it big enough to store vertices in
        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
    });
    device.queue.writeBuffer(vertexBuffer, 0, vertices, 0, vertices.length);

    // create rendering pipeline
    /**
     * 1. first create an object that describes the required layout of our vertex data.
     * 2. 
     */
    const vertexBuffers = [
        {
            attributes: [
                {
                    shaderLocation: 0, //position
                    offset: 0,
                    format: "float32x4",
                },
                {
                    shaderLocation: 1, //color
                    offset: 16,
                    format: "float32x4",
                }
            ],
            arrayStride: 32,
            stepMode: "vertex",
        }
    ];
    
    const pipelineDescriptor = {
        vertex: {
            module: shaderModule,
            entryPoint: "vertex_main",
            buffers: vertexBuffers
        },
        fragment: {
            module: shaderModule,
            entryPoint: "fragment_main",
            targets: [
                {
                    format: navigator.gpu.getPreferredCanvasFormat(),
                },
            ]
        },
        primitive: {
            topology: "triangle-list",
        },
        layout: "auto"
    };

    const renderPipeline = device.createRenderPipeline(pipelineDescriptor);

    const commandEncoder = device.createCommandEncoder();

    const clearColor = { r: 0.0, g: 0.5, b: 1.0, a: 1.0 };

    const renderPassDescriptor = {
        colorAttachments: [
            {
                clearValue: clearColor,
                loadOp: "clear",
                storeOp: "store",
                view: context.getCurrentTexture().createView(),
            }
        ]
    };

    const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
    passEncoder.setPipeline(renderPipeline);
    passEncoder.setVertexBuffer(0, vertexBuffer);
    passEncoder.draw(3);

    passEncoder.end();
    device.queue.submit([commandEncoder.finish()]);

    function frame(){

        const commandEncoder1 = device.createCommandEncoder();

        const clearColor = { r: 0.0, g: 0.5, b: 1.0, a: 1.0 };
    
        const renderPassDescriptor = {
            colorAttachments: [
                {
                    clearValue: clearColor,
                    loadOp: "clear",
                    storeOp: "store",
                    view: context.getCurrentTexture().createView(),
                }
            ]
        };
    
        const passEncoder = commandEncoder1.beginRenderPass(renderPassDescriptor);
        passEncoder.setPipeline(renderPipeline);
        passEncoder.setVertexBuffer(0, vertexBuffer);
        passEncoder.draw(3);
    
        passEncoder.end();
    
        device.queue.submit([commandEncoder1.finish()]);

        requestAnimationFrame(frame);
    }
}

init();